/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package TreeGenerator.Tools;

import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Format;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.util.BufferUtils;
import java.nio.Buffer;
import javax.swing.JOptionPane;

/**
 *
 * @author Jannes
 */
public class CrossSectionControl extends AbstractControl{        
    //relative position
    //  5  4  3
    //   \ | / 
    //6----C----2
    //   / | \ 
    //  7  0  1
    
    private Vector3f camLocation, spatialLocation;
    private Buffer[] buffers = null;
    private static int FRONT = 0;
    private static int FRONT_RIGHT = 1;
    private static int RIGHT = 2;
    private static int BACK_RIGHT = 3;
    private static int BACK = 4;    
    private static int BACK_LEFT = 5;
    private static int LEFT = 6;
    private static int FRONT_LEFT = 7;
    private int currentRelPos;
    private int numberOfSections;
    
    
    public CrossSectionControl(){
        super();        
        currentRelPos = -1;   
        buffers = null;
        /*
        if(buffers == null){            
            createBuffers();
        }          
        */
    }        
        
    private void createBuffers(){
        buffers = new Buffer[8];            
        //int[] indexesFront = {6,5,4,5,6,7, 2,0,1,1,3,2, 30,29,28,29,30,31, 26,24,25,25,27,26, 22,20,21,21,23,22, 18,17,16,17,18,19};
        //int[] indexesBack = {22,20,21,21,23,22, 18,17,16,17,18,19, 10,9,8,9,10,11, 14,12,13,13,15,14, 6,5,4,5,6,7, 2,0,1,1,3,2};        
        numberOfSections = spatial.getVertexCount()/32;        
        int[] indexesFront = new int[12*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){
            int section = getSection(FRONT,i);
            addFrontQuads(indexesFront,30+section*32,0+i*12);
            addBackQuads(indexesFront,26+section*32,6+i*12);
        }                       
        buffers[0] = BufferUtils.createIntBuffer(indexesFront);           

        int[] indexesFrontRight = new int[24*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){ 
            addFrontQuads(indexesFrontRight,30+i*32,0+i*24);
            addFrontQuads(indexesFrontRight,18+i*32,6+i*24);
            addBackQuads(indexesFrontRight,2+i*32,12+i*24);
            addBackQuads(indexesFrontRight,26+i*32,18+i*24);
        }        
        buffers[1] = BufferUtils.createIntBuffer(indexesFrontRight);
        
        int[] indexesRight = new int[12*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){
            addBackQuads(indexesRight,2+i*32,0+i*12);
            addFrontQuads(indexesRight,18+i*32,6+i*12);                
        }        
        buffers[2] = BufferUtils.createIntBuffer(indexesRight);        
        
        int[] indexesBackRight = new int[24*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){             
            addBackQuads(indexesBackRight,14+i*32,0+i*24);
            addFrontQuads(indexesBackRight,18+i*32,6+i*24);
            addBackQuads(indexesBackRight,2+i*32,12+i*24);
            addFrontQuads(indexesBackRight,10+i*32,18+i*24);
        }        
        buffers[3] = BufferUtils.createIntBuffer(indexesBackRight);
        
        int[] indexesBack = new int[12*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){
            addBackQuads(indexesBack,14+i*32,0+i*12);
            addFrontQuads(indexesBack,10+i*32,6+i*12);                
        }        
        buffers[4] = BufferUtils.createIntBuffer(indexesBack);
        
        int[] indexesBackLeft = new int[24*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){             
            addFrontQuads(indexesBackLeft,10+i*32,0+i*24);
            addFrontQuads(indexesBackLeft,6+i*32,6+i*24);
            addBackQuads(indexesBackLeft,22+i*32,12+i*24);
            addBackQuads(indexesBackLeft,14+i*32,18+i*24);
            
        }        
        buffers[5] = BufferUtils.createIntBuffer(indexesBackLeft);
        
        int[] indexesLeft = new int[12*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){
            addFrontQuads(indexesLeft,6+i*32,0+i*12);
            addBackQuads(indexesLeft,22+i*32,6+i*12);                
        }        
        buffers[6] = BufferUtils.createIntBuffer(indexesLeft);        
        
        int[] indexesFrontLeft = new int[24*numberOfSections];
        for(int i = 0; i < numberOfSections; i++){ 
            addFrontQuads(indexesFrontLeft,6+i*32,0+i*24);
            addFrontQuads(indexesFrontLeft,30+i*32,6+i*24);            
            addBackQuads(indexesFrontLeft,26+i*32,12+i*24);
            addBackQuads(indexesFrontLeft,22+i*32,18+i*24);                                    
        }        
        buffers[7] = BufferUtils.createIntBuffer(indexesFrontLeft);
    }        
    
    private void addFrontQuads(int[] indexes, int startIndex,int arrayIndex){
        indexes[arrayIndex] = startIndex;
        indexes[arrayIndex+1] = startIndex-1;
        indexes[arrayIndex+2] = startIndex-2;
        indexes[arrayIndex+3] = startIndex-1;
        indexes[arrayIndex+4] = startIndex;
        indexes[arrayIndex+5] = startIndex+1;
    }
    
    private void addBackQuads(int[] indexes, int startIndex,int arrayIndex){
        indexes[arrayIndex] = startIndex;
        indexes[arrayIndex+1] = startIndex-2;
        indexes[arrayIndex+2] = startIndex-1;
        indexes[arrayIndex+3] = startIndex-1;
        indexes[arrayIndex+4] = startIndex+1;
        indexes[arrayIndex+5] = startIndex;
    }
    
    private int getSection(int position, int sectionIndex){
        if(position == FRONT){
            return numberOfSections-sectionIndex-1;
        }else{
            return sectionIndex;
        }
    }
    
    @Override
    protected void controlUpdate(float tpf) {        
    }
    
    //relative position
    //  3  4  5
    //   \ | / 
    //2----C----6
    //   / | \ 
    //  1  0  7
    
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {        
        if(buffers == null && spatial != null){
            createBuffers();
        }
        if(buffers != null){
            Camera cam = vp.getCamera();
            camLocation = cam.getLocation();        
            spatialLocation = spatial.getWorldTranslation();        
            int newRelPos = 0;
            float zDist = spatialLocation.z - camLocation.z;
            float xDist = spatialLocation.x - camLocation.x;
            float tan = FastMath.abs(xDist)/FastMath.abs(zDist);   
            //System.out.println(tan);
            if(zDist > 0){            
                //front part            
                if(tan < 0.5f){
                    newRelPos = FRONT;
                }else if(tan < 3.0f){                    
                    if(xDist > 0){
                        newRelPos = FRONT_RIGHT;
                    }else{
                        newRelPos = FRONT_LEFT;
                    }
                }else{
                    if(xDist > 0){
                        newRelPos = RIGHT;
                    }else{
                        newRelPos = LEFT;
                    }
                }            
            }else{
                //back part
                if(tan < 0.5f){
                    newRelPos = BACK;
                }else if(tan < 3.0f){                    
                    if(xDist > 0){
                        newRelPos = BACK_RIGHT;
                    }else{
                        newRelPos = BACK_LEFT;
                    }
                }else{
                    if(xDist > 0){
                        newRelPos = RIGHT;
                    }else{
                        newRelPos = LEFT;
                    }
                }            
            }        
            if(newRelPos != currentRelPos){   
                System.out.println("newPos: " + newRelPos);
                currentRelPos = newRelPos;
                ((Geometry)spatial).getMesh().getBuffer(Type.Index).updateData(buffers[currentRelPos]); 
                VertexBuffer[] lods = new VertexBuffer[3];
                lods[0] = new VertexBuffer(Type.Index);
                lods[0].setupData(Usage.Dynamic, 1, Format.UnsignedInt, BufferUtils.createIntBuffer(new int[0]));
                lods[1] = new VertexBuffer(Type.Index);
                lods[1].setupData(Usage.Dynamic, 1, Format.UnsignedInt, BufferUtils.createIntBuffer(new int[0]));    
                lods[2] = new VertexBuffer(Type.Index);
                lods[2].setupData(Usage.Dynamic, 1, Format.UnsignedInt, buffers[currentRelPos]);    
                ((Geometry)spatial).getMesh().setLodLevels(lods);             
            }  
        }
    }

    public Control cloneForSpatial(Spatial spatial) {
        CrossSectionControl control = new CrossSectionControl();
        control.currentRelPos = this.currentRelPos;
        control.buffers = null;
        control.setSpatial(spatial);
        return control;       
    }
    
}
